package com.jsg.sl651.util;

import com.jsg.sl651.entity.city.CityDefinition;
import com.jsg.sl651.entity.frame.FrameMessageWrapper;
import com.jsg.sl651.entity.frame.header.MessageHeader;
import com.jsg.sl651.entity.station.AddressOfHydrologicalTelemetryStation;
import com.jsg.sl651.entity.station.OtherTelemetryStationAddresses;
import com.jsg.sl651.entity.station.RemoteTelemetryStationAddress;
import com.jsg.sl651.enums.StationType;
import com.jsg.sl651.enums.WaterSystemZoningCode;
import com.jsg.sl651.enums.WatershedCode;
import io.netty.buffer.ByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class SL651Tool {


    private static final Logger log = LoggerFactory.getLogger(SL651Tool.class);

    public static byte[] mergeAsciiBytesToHexBytes(ByteBuf data, int length) {
        byte[] bytes = ByteUtil.readBytes(data, length);
        return ByteUtil.mergeAsciiBytesToHexBytes(bytes);
    }

    public static byte mergeAsciiBytesToHexBytes(ByteBuf data) {
        return mergeAsciiBytesToHexBytes(data, 2)[0];
    }

    /**
     * 分析遥测站地址字节数组并返回相应的遥测站地址对象。
     *
     * <p>方法核心</p>
     * <ul>
     *     <li>检查输入字节数组是否为空或长度是否为 5。</li>
     *     <li>将字节数组转换为十六进制字符串。</li>
     *     <li>根据十六进制字符串的前缀判断遥测站类型。</li>
     *     <li>如果前缀为 "00"，解析为水文遥测站地址。</li>
     *     <li>否则，解析为其他遥测站地址。</li>
     * </ul>
     *
     * @param bytes 遥测站地址的字节数组
     * @return 解析后的遥测站地址对象 {@link RemoteTelemetryStationAddress}
     * @throws RuntimeException 如果输入字节数组为空或长度不为 5
     */
    public static RemoteTelemetryStationAddress remoteTelemetryStationAnalysis(byte[] bytes) {
        // 检查输入字节数组是否为空或长度是否为 5
        if (bytes == null || (bytes.length != 5 && bytes.length != 10)) {
            throw new RuntimeException("数据长度不对,数据长度必须为 5(hex) 或者 10（ascii） ,当前长度： " + (bytes == null ? "null" : bytes.length));
        }
        String hex;
        if (bytes.length == 5) {
            // 将字节数组转换为十六进制字符串
            hex = ByteUtil.toHex(bytes);
        } else {
            StringBuilder sb = new StringBuilder();
            for (byte aByte : bytes) {
                sb.append((char) aByte);
            }
            hex = sb.toString().trim();
        }
        // 根据十六进制字符串的前缀判断遥测站类型
        if (hex.startsWith("00")) {
            // 解析为水文遥测站地址
            WatershedCode watershedCode = WatershedCode.getByCode(Integer.parseInt(hex.substring(2, 3)));
            WaterSystemZoningCode waterSystemZoningCode = WaterSystemZoningCode.getByCode(watershedCode, Integer.parseInt(hex.substring(3, 5)));
            StationType stationType = StationType.getByCode(Integer.parseInt(hex.substring(5, 6)));
            String numberTypeCode = hex.substring(6);
            return new AddressOfHydrologicalTelemetryStation(hex, watershedCode, waterSystemZoningCode, stationType, numberTypeCode);
        } else {
            // 解析为其他遥测站地址
            CityDefinition cityDefinition = ChineseCity.getCityDefinition(hex.substring(0, 6));
            String address = hex.substring(6);
            return new OtherTelemetryStationAddresses(hex, cityDefinition, address);
        }
    }

    public static RemoteTelemetryStationAddress remoteTelemetryStationAnalysis(String hex) {
        return remoteTelemetryStationAnalysis(ByteUtil.toBytes(hex));
    }


    public static boolean validSl651Crc(ByteBuf data) {
        // 读取需要校验的数据
        int start = data.readerIndex();
        int length = data.readableBytes();
        // 需校验的数据
        byte[] bytes = new byte[length - 2];
        data.getBytes(start, bytes);
        // 期望值
        byte[] crc = new byte[2];
        data.getBytes(start + length - 2, crc);
        int crcInt = (crc[0] & 0xff) << 8 | (crc[1] & 0xff);
        return CRC.crc16(bytes) == crcInt;
    }

    public static byte[] getSl651Crc(byte[] bytes) {
        int crc = CRC.crc16(bytes);
        byte[] crcBytes = new byte[2];
        crcBytes[0] = (byte) (crc >> 8);
        crcBytes[1] = (byte) (crc & 0xff);
        return crcBytes;
    }


    public static void logFrameMessageWrapper(FrameMessageWrapper msg,Logger logger) {
        MessageHeader header = msg.getHeader();
        logger.info("SL651-2014规约协议打印：\r\n==========================\r\n" +
                "报文编码类型：{}          \r\n=============报头==========\r\n " +
                "中心站地址：{} \r\n水文站类型：{} \r\n遥测站地址信息：{} \r\n密码：{} \r\n报文方向：{} \r\n报文长度：{} \r\n功能码: {} \r\n" +
                        "=============报文==========\r\n" +
                        "{}",
                msg.getMessageType().getDesc(),
                ByteUtil.toHex(header.getCentralStationAddress()),
                header.isHydroStation() ? "水文站" : "非水文站",
                header.getRemoteTelemetryStationAddress().toString(),
                header.getPassword(),
                header.getIdentificationAndLength().getMessageDirection().getDesc(),
                header.getIdentificationAndLength().getLength(),
                header.getFunction().getDesc(),
                msg.getBodyData() == null ? "null" : ByteUtil.toHex(msg.getBodyData())
                );
    }
}
